home *** CD-ROM | disk | FTP | other *** search
- #include "PCMD.h"
- #include "fp.h"
-
- #include "kSanMethodPlugIn.h"
- #include "kSanSimulationPrivate.h"
- #include "VSList.h"
- #define bigVelocityErr -101
- #define smallVelocityErr -102
-
- short PCMDMethodConstructor (KozoDispatchStack *ds, constructorMethodArgs *cma);
- short PCMDMethodDestructor (KozoDispatchStack *ds, destructorMethodArgs* dma);
- short PCMDMethodDoMessage (KozoDispatchStack *ds, doMessageMethodArgs *dmma);
- void PCMDDoCorrection(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, kSanGroup **baseGroup, long numGroups, double *delT);
- void PCMDDoPrediction(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, double *delT);
- short PCMDDoCorrectionFreeGroups(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, kSanGroup *gp, double *delTPtr);
- short PCMDDoCorrectionBlockGroups(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, kSanGroup *gp, double *delTPtr);
- short PCMDDoCorrectionFixedGroups(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, kSanGroup *gp, double *delTPtr);
- short PCMDDoCorrectionMixedGroups(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, kSanGroup *gp, double *delTPtr);
- short PCMDIteration ( kSanMethodPlugIn *mpi, kSanSimulation *sim) ;
- void normalIteration(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, double *delTPtr);
- short PCMDMethodSaveSig(kozoObject *pcmdObj, PCMDMethod *mpi);
- void zeroDerivs(kozoObject *pcmdObj, PCMDMethod *pcmd);
- short PCReallocate(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim);
- void PCMDReleaseDerivs( PCMDMethod *pcmd);
- PCMDDerivatives * PCMDLockDerivs( PCMDMethod *pcmd);
-
- short PCChangedInfo (kozoObject *pcmdObj, PCMDMethod *pcmd, whatWasChangedStruct *wwc);
-
- short initClassPCMDMethod(void)
- {
- short err = noErr;
- kozoClass *newClass;
- kozoObject *co;
-
- newClass = addClass(&co,ClassPCMDMethod, ClassMethodPlugIn, sizeof (PCMDMethod), "PCMD method");
- if (newClass)
- {
- err = setFuncs(newClass, 0L, PCMDMethodConstructor,
- PCMDMethodDestructor, nilPointer, nilPointer, PCMDMethodDoMessage,
- nilPointer, nilPointer, nilPointer, nilPointer);
- }
- return (err);
- }
- short PCMDMethodConstructor (KozoDispatchStack *ds, constructorMethodArgs *cma)
- {
- short err = noErr;
- PCMDMethod *pcmd = nilPointer;
- kSanMethodPlugIn *mpi = nilPointer;
- kSanSimulation *sim = nilPointer;
-
- mpi = KDSGetPrivateData(ds, ClassMethodPlugIn );
-
- pcmd = KDSGetPrivateData(ds, ClassPCMDMethod );
-
- VSListInitialize (&pcmd->derivs, sizeof(PCMDDerivatives));
-
- pcmd->alpha.nought = 3.0 / 16.0;
- pcmd->alpha.one = 251.0 / 360.0;
- pcmd->alpha.two = 1.0;
- pcmd->alpha.three = 11.0 / 18.0;
- pcmd->alpha.four = 1.0 / 6.0;
- pcmd->alpha.five = 1.0 / 60.0;
- pcmd->dirtyDerivs = true;
- mpi->methodPlugPrivateData = pcmd;
- mpi->doIteration = PCMDIteration;
-
-
-
- err = dispatchLoop(ds, cma); // need this because of the get object in hierarchy
- err = kozoObjectGetObjectInHierarchy(cma->container, ClassSimulation , nilPointer, (void **)&sim);
-
- //err = dispatchMessageReport ( cma->container, ClassKozoObject, kGetSimulationPtrMessage, typeSimulationPtrPtr, &sim);
- if (!err)
- {
- err = PCReallocate(ds->obj, pcmd, sim);
- }
-
- KDSReturnError(ds,err);
- }
-
- short PCReallocate(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim)
- {
- short err = noErr;
- long numParts = 0;
- dispatchCount(simOBJ(sim), ClassParticle, &numParts);
- VSListExpandToSize(&pcmd->derivs, numParts);
- if (!err) zeroDerivs(pcmdObj, pcmd);
- return (err);
- }
-
- void PCMDReleaseDerivs( PCMDMethod *pcmd)
- {
- VSListRelease(&pcmd->derivs);
- }
-
- PCMDDerivatives * PCMDLockDerivs( PCMDMethod *pcmd)
- {
- PCMDDerivatives *baseDs;
- baseDs = (PCMDDerivatives *) VSListLock(&pcmd->derivs);
- return (baseDs);
- }
-
- void zeroDerivs(kozoObject *pcmdObj, PCMDMethod *pcmd)
- {
- short err = noErr;
- long partArrIndex;
- long numParts = 0;
- particle *basePart = nilPointer;
- kSanSimulation *sim = nilPointer;
- PCMDDerivatives zeroDeriv;
-
- zerokSanVectorD(&zeroDeriv.accel);
- zerokSanVectorD(&zeroDeriv.thirdD);
- zerokSanVectorD(&zeroDeriv.fourthD);
- zerokSanVectorD(&zeroDeriv.fifthD);
-
- pcmd->derivs.howManyItems = 0;
- err = kozoObjectGetObjectInHierarchy(pcmdObj->container, ClassSimulation, nilPointer, (void **)&sim);
- //err = dispatchMessageReport(pcmdObj, ClassMethodPlugIn, kGetSimulationPtrReport, typeSimulationPtrPtr, &sim);
- if (!err)
- {
- dispatchCount(simOBJ(sim), ClassParticle, &numParts);
- basePart = simLockParts(sim);
- for (partArrIndex = 0; partArrIndex<numParts; ++partArrIndex)
- {
- zeroDeriv.oldPosition = basePart->basePosition[partArrIndex];
- VSListAdd(&pcmd->derivs, (Ptr) &zeroDeriv);
- }
- simReleaseParts(sim);
- }
- }
- short PCMDMethodDestructor (KozoDispatchStack *ds, destructorMethodArgs* dma)
- {
- #pragma unused(dma)
- PCMDMethod *pcmd;
-
- pcmd = KDSGetPrivateData(ds, ClassPCMDMethod );
- VSListDispose (&pcmd->derivs);
- KDSReturnContinue(ds);
- }
-
- short PCMDMethodDoMessage (KozoDispatchStack *ds, doMessageMethodArgs *dmma)
- {
- short err = noErr;
- PCMDMethod *pcmd;
-
- pcmd = KDSGetPrivateData(ds, ClassPCMDMethod );
- switch (dmma->message)
- {
- case kThermalizeMessage:
- case kSetToZeroMessage:
- dispatchLoop(ds, dmma);
- pcmd->dirtyDerivs = true;
- break;
- case kSanChangedInfoMessage :
- err = PCChangedInfo(ds->obj,pcmd, (whatWasChangedStruct *) dmma->data);
- break;
- default :
- KDSReturnContinue(ds);
- }
- KDSDoneDispatch(ds);
- KDSReturnError(ds, err);
- }
- short PCChangedInfo (kozoObject *pcmdObj, PCMDMethod *pcmd, whatWasChangedStruct *wwc)
- {
- short err = noErr;
- pcmd->dirtyDerivs = true;
- if (wwc->numParts)
- {
- err = PCReallocate(pcmdObj, pcmd, wwc->sim);
- }
- return (err);
- }
-
- void pcmdCalcInitialDerivs(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, double *delTPtr);
- void pcmdCalcInitialDerivs(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, double *delTPtr)
- {
- // the idea of this function is that when the derivatives are not initialized, sudden changes in the lower derivatives mean very big changes in
- // the higher derivatives. By making guesses at the lower derivatives before initializing the higher derivatives, we reduce the
- // initial error due to setting initial values for the higher derivatives
- short err = noErr;
- long count;
- long i;
- double delT;
- PCMDDerivatives * baseDerivs;
- baseDerivs = PCMDLockDerivs( pcmd);
-
- dispatchCount(simOBJ(sim), ClassParticle, &count);
- // for delT / 8 predict second deriv;
- for ( i = 0; i < count; ++i)
- { // set the higher derivatives to zero because their values are no good
- // at this stage, we keep only the value for acceleration
- zerokSanVectorD (&baseDerivs[i].accel);
- zerokSanVectorD (&baseDerivs[i].thirdD);
- zerokSanVectorD (&baseDerivs[i].fourthD);
- zerokSanVectorD (&baseDerivs[i].fifthD);
- }
- delT = (*delTPtr) * 0.125;
- normalIteration(pcmdObj, pcmd, sim, basePart, &delT);
-
- for ( i = 0; i < count; ++i)
- { // set the higher derivatives to zero because their values are no good
- // at this stage, we keep only the value for acceleration
- zerokSanVectorD (&baseDerivs[i].thirdD);
- zerokSanVectorD (&baseDerivs[i].fourthD);
- zerokSanVectorD (&baseDerivs[i].fifthD);
- }
- // for delT / 4 predict third deriv;
- delT = (*delTPtr) * 0.25;
- normalIteration(pcmdObj, pcmd, sim, basePart, &delT);
- for ( i = 0; i < count; ++i)
- { // set the higher derivatives to zero
- // because we guessed at the acceleration value last time, the value for third derivative should be good here
- zerokSanVectorD (&baseDerivs[i].fourthD);
- zerokSanVectorD (&baseDerivs[i].fifthD);
- }
- // for delT / 2 predict fourth deriv;
- delT = (*delTPtr) * 0.5;
- normalIteration(pcmdObj, pcmd, sim, basePart, &delT);
- for ( i = 0; i < count; ++i)
- { // set the higher derivatives to zero
- // because we have reasonable values for second and third derivatives, the value for forth derivative here
- // should be acceptable we guess that the fifth derivative will initially be zero.
- zerokSanVectorD (&baseDerivs[i].fifthD);
- }
- pcmd->dirtyDerivs = false;
- // predict initially fifth deriv = 0;
- }
- void PCMDDoPrediction(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, double *delTPtr)
- {
- #pragma unused(sim)
- long partArrIndex;
- long numParts;
- PCMDDerivatives * baseDerivs;
- PCMDDerivatives * theseDs;
- double delT;
- double delTSquOverTwo;
- double delTCubeOverSix;
- double delTFourthOverTwentyFour;
- double delTFifthOverOneTwenty;
- kSanVector oldFourthDif;
- kSanVector oldThirdDif;
- kSanVector oldAccel;
- kSanVector oldVel;
- baseDerivs = PCMDLockDerivs( pcmd);
-
- delT = *delTPtr ;
- delTSquOverTwo = delT * delT * 0.5;
- delTCubeOverSix = delTSquOverTwo * delT * 0.3333333333333;
- delTFourthOverTwentyFour = delTCubeOverSix * delT * 0.25;
- delTFifthOverOneTwenty = delTFourthOverTwentyFour * delT * 0.2;
- dispatchCount(OHOCtr(pcmdObj), ClassParticle, &numParts);
- partArrIndex = 0;
- while (partArrIndex< numParts)
- {
- theseDs = &(baseDerivs[partArrIndex]);
- oldFourthDif = theseDs->fourthD;
- oldThirdDif = theseDs->thirdD;
- oldAccel = theseDs->accel;
- oldVel = basePart->baseVelocity[partArrIndex];
- // save oldPosition for gear group management
- theseDs->oldPosition = basePart->basePosition[partArrIndex];
-
- //predict fourth differential
- theseDs->fourthD.a = oldFourthDif.a + theseDs->fifthD.a * delT;
- theseDs->fourthD.b = oldFourthDif.b + theseDs->fifthD.b * delT;
- #ifndef __2DVectors__
- theseDs->fourthD.c = oldFourthDif.c + theseDs->fifthD.c * delT;
- #endif
- //predict third differential
- theseDs->thirdD.a = oldThirdDif.a +
- oldFourthDif.a * delT +
- theseDs->fifthD.a * delTSquOverTwo;
- theseDs->thirdD.b = oldThirdDif.b +
- oldFourthDif.b * delT +
- theseDs->fifthD.b * delTSquOverTwo;
- #ifndef __2DVectors__
- theseDs->thirdD.c = oldThirdDif.c +
- oldFourthDif.c * delT +
- theseDs->fifthD.c * delTSquOverTwo;
- #endif
-
- //predict second differential
- theseDs->accel.a = oldAccel.a +
- oldThirdDif.a * delT +
- oldFourthDif.a * delTSquOverTwo +
- theseDs->fifthD.a * delTCubeOverSix;
- theseDs->accel.b = oldAccel.b +
- oldThirdDif.b * delT +
- oldFourthDif.b * delTSquOverTwo +
- theseDs->fifthD.b * delTCubeOverSix;
- #ifndef __2DVectors__
- theseDs->accel.c = oldAccel.c +
- oldThirdDif.c * delT +
- oldFourthDif.c * delTSquOverTwo +
- theseDs->fifthD.c * delTCubeOverSix;
- #endif
-
- //predict first differential
- basePart->baseVelocity[partArrIndex].a = oldVel.a +
- oldAccel.a * delT +
- oldThirdDif.a * delTSquOverTwo +
- oldFourthDif.a * delTCubeOverSix +
- theseDs->fifthD.a * delTFourthOverTwentyFour;
- basePart->baseVelocity[partArrIndex].b = oldVel.b +
- oldAccel.b * delT +
- oldThirdDif.b * delTSquOverTwo +
- oldFourthDif.b * delTCubeOverSix +
- theseDs->fifthD.b * delTFourthOverTwentyFour;
- #ifndef __2DVectors__
- basePart->baseVelocity[partArrIndex].c = oldVel.c +
- oldAccel.c * delT +
- oldThirdDif.c * delTSquOverTwo +
- oldFourthDif.c * delTCubeOverSix +
- theseDs->fifthD.c * delTFourthOverTwentyFour;
- #endif
-
-
- //predict position
- basePart->basePosition[partArrIndex].a = theseDs->oldPosition.a +
- oldVel.a * delT +
- oldAccel.a * delTSquOverTwo +
- oldThirdDif.a * delTCubeOverSix +
- oldFourthDif.a * delTFourthOverTwentyFour +
- theseDs->fifthD.a * delTFifthOverOneTwenty;
- basePart->basePosition[partArrIndex].b = theseDs->oldPosition.b +
- oldVel.b * delT +
- oldAccel.b * delTSquOverTwo +
- oldThirdDif.b * delTCubeOverSix +
- oldFourthDif.b * delTFourthOverTwentyFour +
- theseDs->fifthD.b * delTFifthOverOneTwenty;
- #ifndef __2DVectors__
- basePart->basePosition[partArrIndex].c = theseDs->oldPosition.c +
- oldVel.c * delT +
- oldAccel.c * delTSquOverTwo +
- oldThirdDif.c * delTCubeOverSix +
- oldFourthDif.c * delTFourthOverTwentyFour +
- theseDs->fifthD.c * delTFifthOverOneTwenty;
- #endif
- ++partArrIndex;
- }
- PCMDReleaseDerivs( pcmd);
- }
-
- short PCMDDoCorrectionFreeGroups(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, kSanGroup *gp, double *delTPtr);
- short PCMDDoCorrectionFreeGroups(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, kSanGroup *gp, double *delTPtr)
- {
- #pragma unused(pcmdObj)
- long i;
- long count;
- long partArrIndex;
- long *list;
- char largeCorrection = false;
- PCMDDerivatives *theseDs;
- PCMDDerivatives *baseDerivs;
- kSanAtomtype **baseAT;
- double thisFactor;
- double delT;
- double inverseMass;
- double inverseDelT;
- double delTSquOverTwo;
- kSanVector corrFac ; // correctionFactor delR2 in X, Y, Z
-
- delT = (*delTPtr);
- inverseDelT = 1.0 / delT ;
- delTSquOverTwo = delT * delT * 0.5;
- baseAT = simLockAtomTypes(sim);
-
- baseDerivs = PCMDLockDerivs( pcmd);
- count = OHListCount(&gp->particles);
- list = lockList(&gp->particles);
- for(i=0;i<count;++i)
- {
- partArrIndex = list[i];
- theseDs = &(baseDerivs[partArrIndex]);
- inverseMass = baseAT[BPNthType(basePart, partArrIndex)]->specs.inverseMass;
-
- corrFac.a = (basePart->baseForce[partArrIndex].a * inverseMass) - theseDs->accel.a ; // accel was predicted
- corrFac.b = (basePart->baseForce[partArrIndex].b * inverseMass) - theseDs->accel.b ;
- #ifndef __2DVectors__
- corrFac.c = (basePart->baseForce[partArrIndex].c * inverseMass) - theseDs->accel.c ;
- #endif
- multkSanVectorD (&corrFac, delTSquOverTwo, &corrFac );
-
- basePart->basePosition[partArrIndex].a = basePart->basePosition[partArrIndex].a + (pcmd->alpha.nought * corrFac.a);
- basePart->basePosition[partArrIndex].b = basePart->basePosition[partArrIndex].b + (pcmd->alpha.nought * corrFac.b);
- #ifndef __2DVectors__
- basePart->basePosition[partArrIndex].c = basePart->basePosition[partArrIndex].c + (pcmd->alpha.nought * corrFac.c);
- #endif
-
-
- #ifndef __2DVectors__
- if ( (fabs(corrFac.a) + fabs(corrFac.b) + fabs (corrFac.c)) > 0.1 )
- #else
- if ( (fabs(corrFac.a) + fabs(corrFac.b) ) > 0.1 )
- #endif
- {
- largeCorrection = true;
- }
-
- multkSanVectorD (&corrFac, inverseDelT, &corrFac );
-
- basePart->baseVelocity[partArrIndex].a = basePart->baseVelocity[partArrIndex].a + (pcmd->alpha.one * corrFac.a);
- basePart->baseVelocity[partArrIndex].b = basePart->baseVelocity[partArrIndex].b + (pcmd->alpha.one * corrFac.b);
-
- #ifndef __2DVectors__
- basePart->baseVelocity[partArrIndex].c = basePart->baseVelocity[partArrIndex].c + (pcmd->alpha.one * corrFac.c);
- #endif
-
- // correctAccel
- thisFactor = 2.0 * inverseDelT;
- multkSanVectorD (&corrFac, thisFactor, &corrFac );
-
- theseDs->accel.a = theseDs->accel.a + (pcmd->alpha.two * corrFac.a);
- theseDs->accel.b = theseDs->accel.b + (pcmd->alpha.two * corrFac.b);
- #ifndef __2DVectors__
- theseDs->accel.c = theseDs->accel.c + (pcmd->alpha.two * corrFac.c);
- #endif
- // correctThirdDif
- thisFactor = 3.0 * inverseDelT;
- multkSanVectorD (&corrFac, thisFactor, &corrFac );
- theseDs->thirdD.a = theseDs->thirdD.a + (pcmd->alpha.three * corrFac.a);
- theseDs->thirdD.b = theseDs->thirdD.b + (pcmd->alpha.three * corrFac.b);
- #ifndef __2DVectors__
- theseDs->thirdD.c = theseDs->thirdD.c + (pcmd->alpha.three * corrFac.c);
- #endif
- // correctFourthDif
- thisFactor = 4.0 * inverseDelT;
- multkSanVectorD (&corrFac, thisFactor, &corrFac );
- theseDs->fourthD.a = theseDs->fourthD.a + (pcmd->alpha.four * corrFac.a);
- theseDs->fourthD.b = theseDs->fourthD.b + (pcmd->alpha.four * corrFac.b);
- #ifndef __2DVectors__
- theseDs->fourthD.c = theseDs->fourthD.c + (pcmd->alpha.four * corrFac.c);
- #endif
- // correctFifthDif
- thisFactor = 5.0 * inverseDelT;
- multkSanVectorD (&corrFac, thisFactor, &corrFac );
- theseDs->fifthD.a = 0.5 * theseDs->fifthD.a + (pcmd->alpha.five * corrFac.a);
- theseDs->fifthD.b = 0.5 * theseDs->fifthD.b + (pcmd->alpha.five * corrFac.b);
- #ifndef __2DVectors__
- theseDs->fifthD.c = 0.5 * theseDs->fifthD.c + (pcmd->alpha.five * corrFac.c);
- #endif
- }
- PCMDReleaseDerivs( pcmd);
- releaseList(&gp->particles);
- simReleaseAtomTypes(sim);
- return(largeCorrection);
- }
- void PCMDDoCorrection(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, kSanGroup **baseGroup, long numGroups, double *delT)
- {
- short err = noErr;
- long i;
- kSanGroup *gp;
-
- for(i=0; i<numGroups ;++i)
- {
- gp = baseGroup[i];
-
- if ((gp->XYZConstraints[0] == kGroupMovesFreely) &&
- (gp->XYZConstraints[1] == kGroupMovesFreely)
- #ifndef __2DVectors__
- && (gp->XYZConstraints[2] == kGroupMovesFreely)
- #endif
-
- ) // totally free
- {
- err += PCMDDoCorrectionFreeGroups(pcmdObj,pcmd,sim, basePart, gp, delT); // no constraints = empty function
- }
- else if ((gp->XYZConstraints[0] == kGroupIsFixed) &&
- (gp->XYZConstraints[1] == kGroupIsFixed)
- #ifndef __2DVectors__
- && (gp->XYZConstraints[2] == kGroupIsFixed)
- #endif
- ) // fixed
- {
- err +=PCMDDoCorrectionFixedGroups(pcmdObj,pcmd,sim, basePart, gp, delT);
- }
- else if ((gp->XYZConstraints[0] != kGroupMovesFreely) &&
- (gp->XYZConstraints[1] != kGroupMovesFreely)
- #ifndef __2DVectors__
- && (gp->XYZConstraints[2] != kGroupMovesFreely)
- #endif
- ) // moves as a block in 1 2 or 3 axes
- {
- err +=PCMDDoCorrectionBlockGroups(pcmdObj,pcmd,sim, basePart, gp, delT);
- }
- else // some other combination of fixed, block and free
- {
- err +=PCMDDoCorrectionMixedGroups(pcmdObj,pcmd,sim, basePart, gp, delT);
- }
- }
- if (err != 0)
- {
- OHSystemBeep();
- sim->deltaT *= 0.5;
- }
- }
- short PCMDDoCorrectionBlockGroups(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, kSanGroup *gp, double *delTPtr)
- { // each axis eith moves as a group or is fixed, but motion is allowed in at least one direction
- #pragma unused(pcmdObj)
- long i;
- long count;
- long partArrIndex;
- long *list;
- char largeCorrection = false;
- PCMDDerivatives *theseDs;
- PCMDDerivatives *baseDerivs;
- kSanAtomtype **baseAT;
- double delT;
- double inverseDelT;
- kSanVector corrFac ; // correctionFactor delR2 in X
- //double corrFacB; // correctionFactor delR2 in Y
- // double corrFacC; // correctionFactor delR2 in Z
- double netMass;
- kSanVector netForce;
- kSanVector realAccel;
- kSanVector netAccel;
- kSanVector netMoment;
- kSanVector netVelocity;
- kSanVector netThirdD;
- kSanVector netFourthD;
- kSanVector netFifthD;
- kSanVector thirdDiff;
- kSanVector fourthDiff;
- kSanVector fifthDiff;
- kSanVector displacement;
-
- delT = (*delTPtr);
- inverseDelT = 1.0 / delT ;
-
- netMass = 0;
- zerokSanVectorD(& fifthDiff);
- zerokSanVectorD(& fourthDiff);
- zerokSanVectorD(& thirdDiff);
- zerokSanVectorD(& netAccel);
- zerokSanVectorD(& netForce);
- zerokSanVectorD(& netMoment);
- zerokSanVectorD(& netFifthD);
- zerokSanVectorD(& netFourthD);
- zerokSanVectorD(& netThirdD);
-
- baseAT = simLockAtomTypes(sim);
- baseDerivs = PCMDLockDerivs( pcmd);
- count = OHListCount(&gp->particles);
- list = lockList(&gp->particles);
- for(i=0;i<count;++i)
- {
- double thisMass ;
- partArrIndex = list[i];
- thisMass = baseAT[BPNthType(basePart, partArrIndex)]->specs.mass;
- theseDs = &(baseDerivs[partArrIndex]);
- netMass += thisMass; // sum masses, forces and moments
- addkSanVectorsD (&netFifthD, &theseDs->fifthD, &netFifthD );
- addkSanVectorsD (&netFourthD, &theseDs->fourthD, &netFourthD );
- addkSanVectorsD (&netThirdD, &theseDs->thirdD, &netThirdD );
- addkSanVectorsD (&netAccel, &theseDs->accel, &netAccel );
- addkSanVectorsD (&netForce, &basePart->baseForce[partArrIndex], &netForce );
-
- netMoment.a += basePart->baseVelocity[partArrIndex].a * thisMass;
- netMoment.b += basePart->baseVelocity[partArrIndex].b * thisMass;
- #ifndef __2DVectors__
- netMoment.c += basePart->baseVelocity[partArrIndex].c * thisMass;
- #endif
- }
- {
- double inverseNetMass;
- double inverseCount;
- inverseNetMass = 1.0 / netMass;
- inverseCount = 1.0 / ((double)count);
- multkSanVectorD(&netForce, inverseNetMass, &realAccel);
- multkSanVectorD(&netMoment, inverseNetMass, &netVelocity);
- multkSanVectorD(&netAccel, inverseCount, &netAccel);
- multkSanVectorD(&netThirdD, inverseCount, &netThirdD);
- multkSanVectorD(&netFourthD, inverseCount, &netFourthD);
- multkSanVectorD(&netFifthD, inverseCount, &netFifthD);
- }
- {
- subkSanVectorsD (&realAccel, &netAccel, &corrFac );
- //corrFacA = realAccel.a - netAccel.a ;
- //corrFacB = realAccel.b - netAccel.b ;
- //corrFacC = realAccel.c - netAccel.c ;
- {
- double delTSquOverTwo ;
- delTSquOverTwo = delT * delT * 0.5;
- multkSanVectorD(&corrFac, delTSquOverTwo, &corrFac);
-
-
- #ifndef __2DVectors__
- if ( (fabs(corrFac.a) + fabs(corrFac.b) + fabs(corrFac.c)) > 0.1 )
- #else
- if ( (fabs(corrFac.a) + fabs(corrFac.b) ) > 0.1 )
- #endif
- {
- largeCorrection = true;
- }
-
- }
- displacement.a = pcmd->alpha.nought * corrFac.a *
- ((gp->XYZConstraints[0] == kGroupIsFixed) ? 0 : 1); // tricky: this is zero if fixed, one if a block
- displacement.b = pcmd->alpha.nought * corrFac.b *
- ((gp->XYZConstraints[1] == kGroupIsFixed) ? 0 : 1); // tricky: this is zero if fixed, one if a block
- #ifndef __2DVectors__
- displacement.c = pcmd->alpha.nought * corrFac.c *
- ((gp->XYZConstraints[2] == kGroupIsFixed) ? 0 : 1); // tricky: this is zero if fixed, one if a block
- #endif
-
- multkSanVectorD(&corrFac, inverseDelT, &corrFac);
-
- netVelocity.a = (basePart->baseVelocity[partArrIndex].a + (pcmd->alpha.one * corrFac.a)) *
- gp->XYZConstraints[0];
- netVelocity.b = (basePart->baseVelocity[partArrIndex].b + (pcmd->alpha.one * corrFac.b)) *
- gp->XYZConstraints[1];
- #ifndef __2DVectors__
- netVelocity.c = (basePart->baseVelocity[partArrIndex].c + (pcmd->alpha.one * corrFac.c)) *
- gp->XYZConstraints[2];
- #endif
-
- multkSanVectorD(&corrFac, (6.0 * inverseDelT * inverseDelT), &corrFac);
- multAddkSanVectorsD(&thirdDiff, &corrFac, pcmd->alpha.three, &thirdDiff);
- addkSanVectorsD(&thirdDiff, &netThirdD, &thirdDiff);
-
- multkSanVectorD(&corrFac, (4.0 * inverseDelT), &corrFac);
- multAddkSanVectorsD(&fourthDiff, &corrFac, pcmd->alpha.four, &fourthDiff);
- addkSanVectorsD(&fourthDiff, &netFourthD, &fourthDiff);
-
- multkSanVectorD(&corrFac, (5.0 * inverseDelT), &corrFac);
- multAddkSanVectorsD(&fifthDiff, &corrFac, pcmd->alpha.five, &fifthDiff);
- addkSanVectorsD(&fifthDiff, &netFifthD, &fifthDiff);
- }
-
- for(i=0;i<count;++i)
- // loop over particles
- {
- theseDs = &(baseDerivs[partArrIndex]);
- addkSanVectorsD (&basePart->basePosition[partArrIndex], &displacement, &basePart->basePosition[partArrIndex]);
-
- basePart->baseVelocity[partArrIndex] = netVelocity;
- theseDs->accel = realAccel;
- theseDs->thirdD = thirdDiff;
- theseDs->fourthD = fourthDiff;
- theseDs->fifthD = fifthDiff;
- }
- simReleaseAtomTypes(sim);
- PCMDReleaseDerivs( pcmd);
- return(largeCorrection);
-
- }
- short PCMDDoCorrectionFixedGroups(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, kSanGroup *gp, double *delTPtr)
- {
- #pragma unused(sim)
- #pragma unused(pcmdObj)
- #pragma unused(delTPtr)
- long i;
- long count;
- long partArrIndex;
- long *list;
- kSanVector zeroVec;
- PCMDDerivatives *theseDs;
- PCMDDerivatives *baseDerivs;
-
- zerokSanVectorD(&zeroVec);
-
- baseDerivs = PCMDLockDerivs( pcmd);
- count = OHListCount(&gp->particles);
- list = lockList(&gp->particles);
- for(i=0;i<count;++i)
- {
- partArrIndex = list[i];
- theseDs = &(baseDerivs[partArrIndex]);
-
-
- basePart->basePosition[partArrIndex] = theseDs->oldPosition;
- basePart->baseVelocity[partArrIndex] = zeroVec;
- theseDs->accel = zeroVec;
- theseDs->thirdD = zeroVec;
- theseDs->fourthD = zeroVec;
- theseDs->fifthD = zeroVec;
- }
- PCMDReleaseDerivs( pcmd);
- return(noErr);
- }
- short PCMDDoCorrectionMixedGroups(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, kSanGroup *gp, double *delTPtr)
- {
- #pragma unused(pcmdObj)
- long j;
- long i;
- long partArrIndex;
- long count;
- long *list;
- char largeCorrection = false;
- PCMDDerivatives *theseDs;
- PCMDDerivatives *baseDerivs;
- kSanAtomtype **baseAT;
- double delT;
- double netMass;
- double netAcc;
- double delTSquOverTwo;
- double inverseDelT;
- double corrFac;
- netMass = 0;
-
-
- delT = (*delTPtr);
- inverseDelT = 1.0 / delT ;
- delTSquOverTwo = delT * delT * 0.5;
- baseAT = simLockAtomTypes(sim);
- baseDerivs = PCMDLockDerivs( pcmd);
- count = OHListCount(&gp->particles);
- list = lockList(&gp->particles);
- for(j=0; j<NUMDIMENSIONS;++j)
- {
- netAcc = 0;
- switch (gp->XYZConstraints[j])
- {
- case kGroupIsFixed:
- for(i=0;i<count;++i)
- {
- long partArrIndex;
- partArrIndex = list[i];
-
- theseDs = &(baseDerivs[partArrIndex]);
- ((double *)&(basePart->basePosition[partArrIndex]))[j] = ((double *)&(theseDs->oldPosition))[j];
- ((double *)&(basePart->baseVelocity[partArrIndex]))[j] = 0;
- ((double *)&(theseDs->accel))[j] = 0;
- ((double *)&(theseDs->thirdD))[j] = 0;
- ((double *)&(theseDs->fourthD))[j] = 0;
- ((double *)&(theseDs->fifthD))[j] = 0;
- }
- break;
- case kGroupMovesAsABlock:
- if (netMass == 0) // add up the mass if we haven't already
- {
- for(i=0;i<count;++i)
- {
- partArrIndex = list[i];
- netMass += baseAT[BPNthType(basePart, partArrIndex)]->specs.mass;
- }
- }
- for(i=0;i<count;++i)
- {
- partArrIndex = list[i];
- netAcc += ((double *)&(basePart->baseForce[partArrIndex]))[j];
- }
- netAcc *= (delT / netMass) ;
- for(i=0;i<count;++i)
- {
- long partArrIndex;
- partArrIndex = list[i];
- theseDs = &(baseDerivs[partArrIndex]);
- corrFac = netAcc - ((double *)&(theseDs->accel))[j] ;
- ((double *)&(theseDs->accel))[j] = netAcc;
-
- corrFac *= delTSquOverTwo;
- if ( fabs(corrFac) > 0.05 ) largeCorrection = true;
-
- // correct position
- ((double *)&(basePart->basePosition[partArrIndex]))[j] += (pcmd->alpha.nought * corrFac);
- // correctVelocity
- corrFac *= inverseDelT;
- ((double *)&(basePart->baseVelocity[partArrIndex]))[j] += (pcmd->alpha.one * corrFac);
- // correctThirdDif
- corrFac *= 6.0 * inverseDelT * inverseDelT;
- ((double *)&(theseDs->thirdD))[j] += (pcmd->alpha.three * corrFac);
- // correctFourthDif
- corrFac *= 4.0 * inverseDelT;
- ((double *)&(theseDs->fourthD))[j] += (pcmd->alpha.four * corrFac);
- // correctFifthDif
- corrFac *= 5.0 * inverseDelT;
- ((double *)&(theseDs->fifthD))[j] += (pcmd->alpha.five * corrFac);
- }
- break;
-
- case kGroupMovesFreely:
- for(i=0;i<count;++i)
- {
- double inverseMass;
- double realAcc;
- partArrIndex = list[i];
- theseDs = &(baseDerivs[i]);
- inverseMass = baseAT[BPNthType(basePart, partArrIndex)]->specs.inverseMass;
- realAcc = ((double *)&(basePart->baseForce[partArrIndex]))[j] * inverseMass;
- corrFac = realAcc - ((double *)&(theseDs->accel))[j] ;
-
-
- ((double *)&(theseDs->accel))[j] = realAcc;
-
- corrFac *= delTSquOverTwo;
- if ( fabs(corrFac) > 0.05 ) largeCorrection = true;
-
- // correct position
- ((double *)&(basePart->basePosition[partArrIndex]))[j] += (pcmd->alpha.nought * corrFac);
- // correctVelocity
- corrFac *= inverseDelT;
- ((double *)&(basePart->baseVelocity[partArrIndex]))[j] += (pcmd->alpha.one * corrFac);
- // correctThirdDif
- corrFac *= 6.0 * inverseDelT * inverseDelT;
- ((double *)&(theseDs->thirdD))[j] += (pcmd->alpha.three * corrFac);
- // correctFourthDif
- corrFac *= 4.0 * inverseDelT;
- ((double *)&(theseDs->fourthD))[j] += (pcmd->alpha.four * corrFac);
- // correctFifthDif
- corrFac *= 5.0 * inverseDelT;
- ((double *)&(theseDs->fifthD))[j] += (pcmd->alpha.five * corrFac);
- }
- break;
- }
- }
- simReleaseAtomTypes(sim);
- PCMDReleaseDerivs( pcmd);
- return(largeCorrection);
- }
-
- short PCMDIteration ( kSanMethodPlugIn *mpi, kSanSimulation *sim)
- {
- short err = noErr;
- // long numParts;
- PCMDMethod *pcmd = mpi->methodPlugPrivateData;
- particle *basePart;
- double delT;
-
- basePart = simLockParts(sim);
- delT = sim->deltaT;
- // numParts = simGetNumParts(sim);
- if (pcmd->dirtyDerivs)
- {
- pcmdCalcInitialDerivs(mpi->mpiObj,pcmd, sim, basePart, &delT);
- }
- else
- {
- normalIteration(mpi->mpiObj,pcmd, sim, basePart, &delT);
- }
- simIncrementStateCount(sim);
- simReleaseParts(sim);
- return (noErr);
- }
- void normalIteration(kozoObject *pcmdObj, PCMDMethod *pcmd, kSanSimulation *sim, particle *basePart, double *delTPtr)
- {
- short err = noErr;
- long numGroups;
- kSanGroup **baseGroup;
- numGroups = simGetNumGroups(sim);
- baseGroup = simLockGroups(sim);
- PCMDDoPrediction(pcmdObj,pcmd, sim, basePart, delTPtr); // prediction
- err = simDoProgressFunction (sim);
-
- if (!err) err = calculateForce(sim);
- if (!err) err = simDoProgressFunction (sim);
- if (!err) PCMDDoCorrection(pcmdObj,pcmd, sim, basePart, baseGroup, numGroups, delTPtr); // prediction
- simReleaseGroups(sim);
- }
-